﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Diagnostics;
//using System.Text.RegularExpressions;
//using System.Diagnostics.Contracts;
//using System.Reflection;
//using System.Threading;
//using System.Globalization;

//using System.Xml.Linq;
//using System.Net;

//using System.Security.Cryptography.X509Certificates;
//using System.Security.Cryptography;
//using System.Security;
//using System.IO;
//using System.Collections;
//using System.Collections.Concurrent;

//using King.Collections;
//using King.Reflection;
//using King.Declarative;
//using King.Extensions;
//using King.Loader;
//using King.Text;
//using King.Text.Xml;
//using King.Xml.Reflection;
//using King.CSharp.Reflection;
//using King.Web.Reflection.Emit;
//using King.Xml.Reflection.Emit;
//using King.Xml.IO;
//using System.Threading.Tasks;
//using King.Rest.Reflection;

//namespace King.Web {
//}

//namespace King.Web.Reflection {

//    public interface IWebNameFormatter {
//        string ToXmlLocalName(string name);
//        string FromXmlLocalName(string name);
//    }

//    public sealed class WebLoader {

//        public static IEnumerable<WebLoader> Create(
//            string path,
//            Func<XNamespace, CSharpNamespace> getNamespace = null) {
//            if (path == null)
//                throw new ArgumentException();

//            // reflection only CSharpLoader
//            var loader = CSharpLoader.Create(new[] { Path.GetDirectoryName(path) });
//            var assemblyName = Path.GetFileNameWithoutExtension(path);
//            return Create(loader.GetAssembly(assemblyName), getNamespace);
//        }
//        public static IEnumerable<WebLoader> Create(
//            Assembly assembly,
//            Func<XNamespace, CSharpNamespace> getNamespace = null) {
//            if (assembly == null || assembly.ReflectionOnly)
//                throw new ArgumentException();

//            // runtime CSharpLoader
//            var loader = CSharpLoader.Create();

//            return Create(loader.GetAssembly(assembly), getNamespace);
//        }
//        public static IEnumerable<WebLoader> Create(
//            CSharpAssembly assembly,
//            Func<XNamespace, CSharpNamespace> getNamespace = null) {
//            var namespaces =
//                assembly.Attributes(typeof(XcsSchemaAttribute))
//                .Select(o => assembly.GetNamespace((string)o.Namespace));

//            return namespaces.Select(o => Create(new[] { o })).ToArray();
//        }
//        public static WebLoader Create(
//            IEnumerable<CSharpNamespace> namespaces,
//            Func<XNamespace, CSharpNamespace> getNamespace = null) {
//            if (namespaces.None())
//                return null;

//            var loaders = namespaces.Select(o => o.Loader).Distinct();
//            if (loaders.MoreThanOne())
//                throw new ArgumentException(
//                    "All C# namespaces must belong to the same C# loader.");

//            return Create(loaders.Single(), namespaces, getNamespace);
//        }
//        public static WebLoader Create(
//            Func<WebScopeFactory, WebScope> scopeFactory,
//            Func<XsSchema, IEnumerable<object>> typeNames,
//            Func<XsTypeFactory, XsType> typeFactory,
//            Func<XsSchema, IEnumerable<object>> attributeGroupNames,
//            Func<XsAttributeGroupFactory, XsAttributeGroup> attributeGroupFactory,
//            Func<XsSchema, IEnumerable<object>> rootElementNames,
//            Func<XsMemberFactory, XsElement> rootElementFactory) {

//            return new WebLoader(
//                scopeFactory: scopeFactory,

//                // types
//                typeFactory: typeFactory,
//                typeNames: typeNames,

//                // attribute groups
//                attributeGroupFactory: attributeGroupFactory,
//                attributeGroupNames: attributeGroupNames,

//                // root elements
//                rootElementFactory: rootElementFactory,
//                rootElementNames: rootElementNames
//            );
//        }

//        internal static Exception ThrowUnexpectedXsConstruction() {
//            throw new ArgumentException("Unsupported xsd construction encountered.");
//        }

//        private static WebLoader Create(
//            CSharpLoader loader,
//            IEnumerable<CSharpNamespace> namespaces,
//            Func<XNamespace, CSharpNamespace> getNamespace
//        ) {
//            return new WebDeclarationLoader(
//                loader,
//                namespaces,
//                getNamespace
//            ).Loader;
//        }

//        private readonly XsLoader m_xsLoader;
//        private readonly Loader<WebScope> m_scopeLoader;

//        private WebLoader(
//            XsLoader xsLoader,
//            Func<WebScopeFactory, WebScope> scopeFactory) {

//            m_xsLoader = xsLoader;

//            m_scopeLoader = Loader<WebScope>.Create(
//                names: o => new object[] { },
//                normalizeName: o => {

//                    // XNamespace
//                    var ns = o as XNamespace;
//                    if (ns == null)
//                        return null;

//                    return ns;
//                },
//                factory: o => {
//                    var factory = new WebScopeFactory(this, o.Name);

//                    // handle creating xsd and king scopes
//                    if (new[] { 
//                        XsLoader.XsdXNamespace, 
//                        XsLoader.KingXNamespace 
//                    }.Contains(o.Name)) {
//                        var schema = m_xsLoader.GetSchema(o.Name);

//                        return factory.CreateScope(
//                            toXmlLocalName: x => x.ToLowerFirst(),
//                            fromXmlLocalName: x => x.ToUpperFirst(),

//                            typeFactory: x => schema.TryGetType(x.XName),
//                            typeNames: x => schema.Types().Select(y => x.FromXName(y.XName))
//                        );
//                    }

//                    // delegate creating scope to user
//                    return scopeFactory(factory);
//                },
//                getLoader: o => o.Loader.m_scopeLoader,
//                getNames: o => new object[] { 
//                    o.XNamespace,
//                },
//                resolve: (o, n) => {
//                    throw new LoaderException("WebLoader failed to resolve scope.", n);
//                }
//            );
//        }

//        public XsLoader XsLoader {
//            get { return m_xsLoader; }
//        }
//        public WebType Object {
//            get { return GetType(RestObjectXName); }
//        }
//        public WebType List {
//            get { return GetType(RestListXName); }
//        }

//        public WebScope Xsd {
//            get { return GetScope(XsLoader.XsdXNamespace); }
//        }
//        public WebScope King {
//            get { return GetScope(XsLoader.KingXNamespace); }
//        }

//        public WebScope TryGetScope(XNamespace xNamespace) {
//            return m_scopeLoader.TryGet(xNamespace);
//        }
//        public WebScope GetScope(XNamespace xNamespace) {
//            return m_scopeLoader.Get(xNamespace);
//        }

//        public WebType GetType(XName name) {
//            return GetScope(name.Namespace).GetType(name);
//        }
//        public WebType TryGetType(XName name) {
//            if (name == null)
//                return null;

//            var scope = TryGetScope(name.Namespace);
//            if (scope == null)
//                return null;

//            return scope.TryGetType(name);
//        }
//    }
//    public sealed class WebScope : WebLoaderObject {

//        private readonly WebLoader m_loader;
//        private readonly XsSchema m_xsSchema;
//        private readonly Func<string, string> m_toXmlLocalName;
//        private readonly Func<string, string> m_fromXmlLocalName;
//        private readonly Loader<WebType> m_typeLoader;

//        private readonly Func<WebTypeFactory, XsType> m_xsTypeFactory;
//        private readonly Func<WebScope, IEnumerable<string>> m_typeNames;

//        internal WebScope(
//            WebLoader loader,
//            XsSchema xSchema,
//            Func<string, string> toXmlLocalName,
//            Func<string, string> fromXmlLocalName,
//            Func<WebTypeFactory, XsType> xsTypeFactory,
//            Func<WebScope, IEnumerable<string>> typeNames,
//            Func<WebScope, object, WebType> typeResolve
//        )
//            : base(loader, xSchema) {

//            m_loader = loader;
//            m_xsSchema = xSchema;

//            m_xsTypeFactory = xsTypeFactory;
//            m_typeNames = typeNames;

//            m_toXmlLocalName = toXmlLocalName ?? (Func<string, string>)(o => o);
//            m_fromXmlLocalName = fromXmlLocalName ?? (Func<string, string>)(o => o);

//            m_typeLoader = Loader<WebType>.Create(
//                names: o => xSchema.Types(),
//                normalizeName: o => {

//                    // xtype
//                    var xsType = o as XsType;
//                    if (xsType == null) {

//                        // xName
//                        var xName = o as XName;
//                        if (xName == null) {

//                            // string
//                            var name = o as string;
//                            if (name == null)
//                                return null;

//                            xName = ToXName(name);
//                        }
//                        xsType = m_xsSchema.TryGetType(xName);
//                    }

//                    if (xsType == null || xsType.Schema != m_xsSchema)
//                        return null;

//                    return xsType;
//                },
//                factory: o => {

//                    var xsType = o.Name;

//                    if (xsType.IsSimpleType)
//                        return new WebSimpleType(this, xsType);

//                    if (xsType.XName == WebLoader.RestObjectXName)
//                        return new WebObjectType(this, xsType);

//                    return null;
//                },
//                getLoader: o => o.Scope.m_typeLoader,
//                getNames: o => new object[] {
//                    o.Name,
//                    o.XName,
//                    o.XsType,
//                },
//                resolve: (s, o) => {
//                    var type = typeResolve(this, o);
//                    if (type == null)
//                        throw new LoaderException(
//                            string.Format("WebScope '{0}' failed to resolve type.", ToString()), o);
//                    return type;
//                }
//            );
//        }

//        internal XsPrefix CreateXsPrefix(XsPrefixFactory factory) {
//            return m_xsPrefixFactory(new WebPrefixFactory(this, factory));
//        }
//        internal IEnumerable<XPrefix> XsPrefixes() {
//            return m_xPrefixes(this);
//        }
//        internal XsType CreatXsType(XsTypeFactory factory) {
//            return m_xsTypeFactory(new WebTypeFactory(this, factory));
//        }
//        internal IEnumerable<object> XsTypeNames() {
//            return m_typeNames(this).Select(o => ToXName(o));
//        }

//        public XsSchema XsSchema {
//            get { return m_xsSchema; }
//        }
//        public XNamespace XNamespace {
//            get { return m_xsSchema.XNamespace; }
//        }
//        public IEnumerable<WebScope> References() {
//            var result =
//                from o in XsSchema.Prefixes()
//                let reference = XsSchema.GetSchema(o)
//                where reference != XsSchema
//                select Loader.GetScope(reference);

//            return result;
//        }

//        public XName ToXName(string name) {
//            if (name == null)
//                return null;
//            return XsSchema.XNamespace + m_toXmlLocalName(name);
//        }
//        public string FromXName(XName name) {
//            if (name == null)
//                return null;
//            return m_fromXmlLocalName(name.LocalName);
//        }

//        public XPrefix GetPrefix(WebScope scope) {
//            return m_xsSchema.GetPrefix(scope.m_xsSchema);
//        }
//        public XPrefix TryGetPrefix(WebScope scope) {
//            return m_xsSchema.TryGetPrefix(scope.m_xsSchema);
//        }

//        public WebScope GetScope(XPrefix prefix) {
//            return Loader.GetScope(m_xsSchema.GetSchema(prefix));
//        }
//        public WebScope TryGetScope(XPrefix prefix) {
//            var schema = m_xsSchema.TryGetSchema(prefix);
//            if (schema == null)
//                return null;

//            return Loader.TryGetScope(schema.XNamespace);
//        }

//        public XQName GetQName(WebType type) {
//            return m_xsSchema.GetQName(type.XsType);
//        }
//        public XQName TryGetQName(WebType type) {
//            return m_xsSchema.TryGetQName(type.XsType);
//        }

//        public IEnumerable<XPrefix> Prefixes() {
//            return m_xsSchema.Prefixes();
//        }

//        public WebType GetType(XQName qName) {
//            return GetType(m_xsSchema.GetType(qName));
//        }
//        public WebType TryGetType(XQName qName) {
//            return TryGetType(m_xsSchema.TryGetType(qName));
//        }

//        public WebType GetType(object name) {
//            return m_typeLoader.Get(name);
//        }
//        public WebType TryGetType(object name) {
//            return m_typeLoader.TryGet(name);
//        }

//        public WebType GetType(string name) {
//            return m_typeLoader.Get(name);
//        }
//        public WebType TryGetType(string name) {
//            return m_typeLoader.TryGet(name);
//        }

//        public WebType GetType(XsType type) {
//            return m_typeLoader.Get(type);
//        }
//        public WebType TryGetType(XsType type) {
//            return m_typeLoader.TryGet(type);
//        }

//        public WebType GetType(XName name) {
//            return m_typeLoader.Get(name);
//        }
//        public WebType TryGetType(XName name) {
//            return m_typeLoader.TryGet(name);
//        }

//        public IEnumerable<WebType> Types() {
//            return m_typeLoader.Where(o => o.Name != null);
//        }

//        public override string ToString() {
//            if (XNamespace == XNamespace.None)
//                return "[XNamespace.None]";
//            return XNamespace.ToString();
//        }
//    }

//    public abstract class WebLoaderObject {
//        private WebLoader m_loader;
//        private XsLoaderObject m_xsLoaderObject;
//        private Lazy<IEnumerable<RestXmlObject>> m_appInfo;
//        private Lazy<string> m_documentation;
//        private Lazy<string> m_comment;

//        internal WebLoaderObject(
//            WebLoader loader,
//            XsLoaderObject xsLoaderObject) {
//            m_loader = loader;
//            m_xsLoaderObject = xsLoaderObject;

//            m_documentation = new Lazy<string>(() => (string)xsLoaderObject.Documentation);
//            m_comment = new Lazy<string>(() => xsLoaderObject.Comment);
//            m_appInfo = new Lazy<IEnumerable<RestXmlObject>>(() => {
//                var xElement = xsLoaderObject.AppInfo;
//                if (xElement == null)
//                    return Enumerable.Empty<RestXmlObject>();

//                // rename the root node to be in the Rest namespace
//                var appInfo = new XElement(WebLoader.RestXNamespace + "appInfo", xElement.Elements());

//                //// deserialize attributes
//                //var message = m_loader.Rest.Deserialize(new StringReader((string)xElement)).Result;

//                //// return result
//                //return message.AppInfo;

//                throw new NotImplementedException();
//            });
//        }

//        public XsLoader XsLoader {
//            get { return m_xsLoaderObject.Loader; }
//        }
//        public XsLoaderObject XsLoaderObject {
//            get { return m_xsLoaderObject; }
//        }
//        public WebLoader Loader {
//            get { return m_loader; }
//        }

//        public IEnumerable<dynamic> AppInfo(RestXmlType type = null) {
//            IEnumerable<RestXmlObject> attributes = m_appInfo.Value;

//            if (type != null)
//                attributes = attributes.Where(o => o.Type.IsOrIsSubclassOf(type));

//            return attributes;
//        }
//        public string Documentation {
//            get { return m_documentation.Value; }
//        }
//        public string Comment {
//            get { return m_comment.Value; }
//        }
//    }
//    public abstract class WebScopeObject : WebLoaderObject {
//        private WebScope m_scope;
//        private XsSchemaObject m_xsSchemaObject;

//        internal WebScopeObject(
//            WebScope scope,
//            XsLoaderObject loaderObject
//        )
//            : base(scope.Loader, loaderObject) {
//            m_scope = scope;
//        }

//        internal WebScopeObject(
//            WebScope scope,
//            XsSchemaObject schemaObject
//        )
//            : base(scope.Loader, schemaObject) {
//            m_scope = scope;
//            m_xsSchemaObject = schemaObject;
//        }

//        public XsSchema XsSchema {
//            get { return m_scope.XsSchema; }
//        }
//        public XsSchemaObject XsSchemaObject {
//            get { return m_xsSchemaObject; }
//        }
//        public XNamespace XNamespace {
//            get { return m_xsSchemaObject.XNamespace; }
//        }
//        public XName XName {
//            get {
//                if (m_xsSchemaObject == null)
//                    return null;
//                return m_xsSchemaObject.XName;
//            }
//        }
//        public string Name {
//            get { return Scope.FromXName(XName); }
//        }
//        public WebScope Scope {
//            get { return m_scope; }
//        }

//        public override string ToString() {
//            if (XName == null)
//                return "[anonymous]";
//            return XName.ToString();
//        }
//    }

//    public abstract class WebType : WebScopeObject {
//        private XsType m_xsType;

//        internal WebType(WebScope scope)
//            : base(scope, scope.XsSchema) {
//        }
//        internal WebType(
//            WebScope scope,
//            XsType xsType
//        )
//            : base(scope, xsType) {

//            m_xsType = xsType;
//        }

//        public WebType BaseType {
//            get { return Loader.TryGetType(XsType.BaseType); }
//        }
//        public bool IsOrIsSubclassOf(WebType type) {
//            if (this == type)
//                return true;

//            if (BaseType == null)
//                return false;

//            return BaseType == type;
//        }

//        // simple type
//        public virtual bool IsSimple {
//            get { return false; }
//        }
//        public virtual XsType XsType {
//            get { return m_xsType; }
//        }

//        // complex type
//        public virtual bool IsComplex {
//            get { return false; }
//        }
//        // list
//        public virtual bool IsList {
//            get { return false; }
//        }
//        public virtual bool IsObject {
//            get { return false; }
//        }

//        public virtual object Deserialize(string value) {
//            throw new InvalidOperationException();
//        }
//        public virtual bool TryDeserialize(string literal, out object value) {
//            throw new InvalidOperationException();
//        }
//    }
//    internal sealed class WebSimpleType : WebType {

//        public WebSimpleType(
//            WebScope scope,
//            XsType xsType
//        )
//            : base(scope, xsType) {
//        }

//        public override bool IsSimple {
//            get { return true; }
//        }
//        public override object Deserialize(string value) {
//            return XsType.Deserialize(value);
//        }
//        public override bool TryDeserialize(string literal, out object value) {
//            return XsType.TryDeserialize(literal, out value);
//        }
//    }
//    internal sealed class WebObjectType : WebType {

//        internal WebObjectType(WebScope scope, XsType xsType)
//            : base(scope, xsType) {
//        }

//        public override bool IsObject {
//            get { return true; }
//        }
//    }
//}

//namespace King.Web.Reflection.Emit {
//    //[XcsNamespace(XsLoader.XsdNamespace)]
//    //public enum WebXsdNamespace {
//    //    AnyType,
//    //    AnySimpleType,
//    //    AnyAtomicType,
//    //    String,
//    //    Boolean,
//    //    Decimal,
//    //    Float,
//    //    Double,
//    //    Base64Binary,
//    //    HexBinary,
//    //    AnyUri,
//    //    QName,
//    //    Duration,
//    //    Date,
//    //    Time,
//    //    DateTime,
//    //    GYear,
//    //    GMonth,
//    //    GDay,
//    //    GYearMonth,
//    //    GMonthDay,
//    //    Integer,
//    //    Long,
//    //    Int,
//    //    Short,
//    //    Sbyte,
//    //    NonNegativeInteger,
//    //    PositiveInteger,
//    //    UnsignedLong,
//    //    UnsignedInt,
//    //    UnsignedShort,
//    //    UnsignedByte,
//    //    NonPositiveInteger,
//    //    NegativeInteger,
//    //    DayTimeDuration,
//    //    YearMonthDuration,
//    //    DateTimeStamp,
//    //}

//    //[XcsNamespace(XsLoader.KingNamespace)]
//    //public enum WebKingNamespace {
//    //    DateTimeStamp,
//    //    Time,
//    //    DateTime,
//    //    Date,
//    //    Year,
//    //    Month,
//    //    Day,
//    //    YearMonth,
//    //    MonthDay,
//    //}
//}